package com.wanfajie.smsdistribute.common.adapter

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Checkable

abstract class CheckedRecyclerAdapter<E>(
        ctx : Context,
        data: Collection<E>,
        private val rowResId : Int,
        private val checkableId : Int
) : SimpleRecyclerAdapter<E, CheckedRecyclerAdapter.CheckedViewHolder>() {

    private val inflater : LayoutInflater = LayoutInflater.from(ctx)

    private var checkStatusMap: HashMap<E, Boolean> = HashMap()

    private var clickListener : View.OnClickListener? = null
    private var longClickListener: View.OnLongClickListener? = null

    override val mItems: MutableList<E> by lazy {
        RecyclerAdapterLinkedList<E, CheckedViewHolder>(this, data)
    }

    private var mCheckable = true

    private val onClick: (View) -> Unit = {
        val vh = it.tag as CheckedViewHolder
        if (mCheckable) {
            toggleCheck(vh)
        }

        clickListener?.onClick(it)
    }

    init {
        super.setOnClickListener(onClick)

        super.setOnLongClickListener {

            val listenerResult = longClickListener?.onLongClick(it) ?: false

            if (!listenerResult) {
                if (!mCheckable) {
                    val vh = it.tag as CheckedViewHolder
                    setItemCheckable(true)
                    setChecked(vh)
                } else {
                    setItemCheckable(false)
                }
            }

            true
        }
    }

    private fun loadCheckableStatus(holder : CheckedViewHolder, index : Int) {
        if (mCheckable) {
            holder.get<View>(checkableId).visibility = View.VISIBLE
        } else {
            holder.get<View>(checkableId).visibility = View.GONE
        }

        holder.isChecked = checkStatusMap[getItem(index)] ?: false
    }

    private fun setChecked(vh: CheckedViewHolder, checked: Boolean = true) {
        vh.isChecked = checked
        checkStatusMap[vh.tag as E] = checked
    }

    private fun toggleCheck(vh: CheckedViewHolder) {
        setChecked(vh, !(checkStatusMap[vh.tag] ?: false))
    }

    fun setItemCheckable(checkable: Boolean) {
        if (checkable != mCheckable) {
            mCheckable = checkable
            all(false)
            notifyDataSetChanged()
        }
    }

    fun isItemCheckable(): Boolean = mCheckable

    fun getCheckedItemList() : List<E> = mItems.filter { checkStatusMap[it] ?: false }

    fun getCheckedCount() : Int = mItems.filter { checkStatusMap[it] ?: false }.count()

    fun isCheckedAll() = mItems.all { checkStatusMap[it] ?: false }

    override fun setOnClickListener(listener: View.OnClickListener?) {
        clickListener = listener
    }

    override fun setOnClickListener(listener: (View) -> Unit) {
        setOnClickListener(View.OnClickListener(listener))
    }

    override fun setOnLongClickListener(listener: View.OnLongClickListener?) {
        longClickListener = listener
    }

    override fun setOnLongClickListener(listener: (View) -> Boolean) {
        setOnLongClickListener(View.OnLongClickListener(listener))
    }

    fun all(checked : Boolean) {
        mItems.forEach { checkStatusMap[it] = checked }
        notifyDataSetChanged()
    }

    fun setChecked(checked: Boolean, vararg indexes: Int) {
        indexes.forEach {
            val item = mItems[it]
            checkStatusMap[item] = checked
        }
        notifyDataSetChanged()
    }

    fun setChecked(checked: Boolean, vararg items: E) {
        items.forEach {
            checkStatusMap[it] = checked
        }
        notifyDataSetChanged()
    }

    fun setChecked(checked: Boolean, collection: Collection<E>) {
        collection.forEach {
            checkStatusMap[it] = checked
        }
        notifyDataSetChanged()
    }

    final override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CheckedViewHolder {
        val view = inflater.inflate(rowResId, p0, false)
        val checkableView = view.findViewById<View>(checkableId)
        val vh = CheckedViewHolder(view, checkableView as Checkable)
        checkableView.tag = vh
        checkableView.setOnClickListener(onClick)
        return vh
    }

    final override fun onBindViewHolder(p0: CheckedViewHolder, p1: Int) {
        super.onBindViewHolder(p0, p1)
        loadCheckableStatus(p0, p1)
        processViewHolder(p0, getItem(p1))
    }

    abstract fun processViewHolder(p0 : CheckedViewHolder, p1 : E)

    fun add(item: E, index: Int) {
        mItems.add(index, item)
        mRecyclerView?.scrollToPosition(index)
    }

    fun addAll(index: Int, elements: List<E>) {
        mItems.addAll(index, elements)
        mRecyclerView?.scrollToPosition(index)
    }

    fun setItems(elements: Collection<E>) {
        mItems.clear()
        mItems.addAll(elements)
        mRecyclerView?.scrollToPosition(0)
    }

    fun remove(element: E) = mItems.remove(element)

    fun removeAll(elements: List<E>? = null) {
        if (elements == null) mItems.clear()
        else mItems.removeAll(elements)
    }

    fun indexOf(element: E) = mItems.indexOf(element)

    class CheckedViewHolder(view : View, checkable: Checkable)
        : RecyclerViewHolder(view), Checkable by checkable
}